/* example graph converting llvm bytecode to journ software

https://joern.io/

https://docs.joern.io/home

https://docs.joern.io/llvm2cpg/hello-llvm/

https://github.com/ShiftLeftSecurity/llvm2cpg

https://github.com/ShiftLeftSecurity/joern

Joern is a platform for robust analysis of C/C++ code. It generates code property graphs, a graph representation of code for cross-language code analysis. Code property graphs are stored in a custom graph database. This allows code to be mined using search queries formulated in a Scala-based domain-specific query language. Joern is developed with the goal of providing a useful tool for vulnerability discovery and research in static program analysis.

See also:
https://blog.llvm.org/posts/2021-02-23-llvm-meets-code-property-graphs/

to analyze sourcecode and the joern-export command line utility can generate dot graph data of source:
In summary, Joern can create the following graph representations for C/C++ code:

    Abstract Syntax Trees (AST)
    Control Flow Graphs (CFG)
    Control Dependence Graphs (CDG)
    Data Dependence Graphs (DDG)
    Program Dependence graphs (PDG)
    Code Property Graphs (CPG14)

This is the source of this graph data:

importCode.c.fromString( """
           int myfunc(int b) {
             int a = 42;
             if (b > 10) {
                foo(a)
             }
             bar(a);
           }
           """
       ) 

the dot representation of the AST as dot is this:

*/

digraph myfunc {  
"1000102" [label = "(METHOD,myfunc)" ]
"1000103" [label = "(PARAM,int b)" ]
"1000104" [label = "(BLOCK,,)" ]
"1000105" [label = "(LOCAL,a: int)" ]
"1000106" [label = "(<operator>.assignment,a = 42)" ]
"1000107" [label = "(IDENTIFIER,a,a = 42)" ]
"1000108" [label = "(LITERAL,42,a = 42)" ]
"1000109" [label = "(CONTROL_STRUCTURE,if (b > 10),if (b > 10))" ]
"1000110" [label = "(<operator>.greaterThan,b > 10)" ]
"1000111" [label = "(IDENTIFIER,b,b > 10)" ]
"1000112" [label = "(LITERAL,10,b > 10)" ]
"1000113" [label = "(BLOCK,,)" ]
"1000114" [label = "(bar,bar(a))" ]
"1000115" [label = "(IDENTIFIER,a,bar(a))" ]
"1000116" [label = "(METHOD_RETURN,int)" ]
  "1000102" -> "1000103"  
  "1000102" -> "1000104"  
  "1000102" -> "1000116"  
  "1000104" -> "1000105"  
  "1000104" -> "1000106"  
  "1000104" -> "1000109"  
  "1000104" -> "1000114"  
  "1000106" -> "1000107"  
  "1000106" -> "1000108"  
  "1000109" -> "1000110"  
  "1000109" -> "1000113"  
  "1000110" -> "1000111"  
  "1000110" -> "1000112"  
  "1000114" -> "1000115"  
}
